<template>
  <div ref="root_node"
       class="gaming">
  </div>
</template>
<script>
import {
  ROOM_STATUS,
  PLAYER_STATUS,
  roomStatusToString,
  playerStatusToString,
} from '../../STATUS';
import rule from '../../core/min_rule';
import Card, { CardList, CARD_LIST } from "../../core/Card";
import render_player, { init_loader as render_player_init_loader } from './render_player';
import { stageComponentGenerator } from '../../core/componentGenerator';
export default stageComponentGenerator({
  name: 'gaming',
  data() {
    return {
      ROOM_STATUS,
      PLAYER_STATUS,
      img_url: {},
      card_list: [],
      top_card_list: [],
      mid_card_list: [],
      btm_card_list: [],
      mul_select_from: null,
      mul_select_to: null,
      is_special: false,
      special_info: {},

      com_two_list: [],
      com_two_pair_list: [],
      com_three_list: [],
      com_straight_list: [],
      com_flush_list: [],
      com_full_house_list: [],
      com_four_list: [],
      com_straight_flush_list: [],

      // 自定义牌组
      is_change_card_list: false,
      CARD_LIST,
      selected_custom_card_list: [],
    }
  },
  created() {
    // 监测特殊牌
    this.$watch("player.card_list", (card_name_list) => {
      const card_list = card_name_list.map(card_name => Card.getIns(card_name));
      CardList.sort_cards(card_list);
      card_list.forEach(card => card.reset());
      this.card_list = card_list;
      // this.card_list.sort_cards();
      this.is_change_card_list = false;
      // 检测是否可以报道
      socket.emit("is-special-card-list", card_name_list);
      socket.once("special-card-list-res", res_info => {
        console.log("special-card-list-res", res_info)
        if (res_info && res_info.type) {
          this.is_special = true;
          this.special_info = res_info;
        } else {
          this.is_special = false;
          this.special_info = null;
        }
      });
    }, {
        immediate: true
      });
    const com_list_map = new Map();
    this.$watch("card_list", (card_list) => {
      // 监测基本的智能牌组
      ["two",
        "two_pair",
        "three",
        "straight",
        "flush",
        "full_house",
        "four",
        "straight_flush",
      ].forEach(type => {
        const useable_card_list = card_list.filter(card => !card.is_used);
        const useable_card_list_val = useable_card_list.join("|");
        const com_key = "com_" + type + "_list";
        if (com_list_map.get(com_key) === useable_card_list_val) {
          return
        }
        com_list_map.set(com_key, useable_card_list_val);
        const com_list = rule["check_" + type](useable_card_list);
        this[com_key] = com_list;
      });
    }, {
        immediate: true,
        deep: true
      });

    // PIXI
    const {
      unwatchers,
      app,
      loader
    } = this;

    loader.add("gaming_bg", "game/Game_UI_01.png");
    loader.add("done_btn", "game/Finish_01.png");
    loader.add("done_hover_btn", "game/Finish_02.png");
    loader.add("clear_btn", "game/retry_01.png");
    loader.add("clear_hover_btn", "game/retry_02.png");
    loader.add("cards_mask_top", "game/Card_UI_03.png");
    loader.add("cards_mask_mid", "game/Card_UI_02.png");
    loader.add("cards_mask_btm", "game/Card_UI_01.png");

    loader.add("auto_two", "game/duizi_00.png");
    loader.add("auto_two_pair", "game/liangdui_01.png");
    loader.add("auto_three", "game/santiao_01.png");
    loader.add("auto_straight", "game/shunzi_01.png");
    loader.add("auto_flush", "game/tonghua_01.png");
    loader.add("auto_full_house", "game/hulu_01.png");
    loader.add("auto_four", "game/zhadan_01.png");
    loader.add("auto_straight_flush", "game/同花顺.png");
    loader.add("auto_special", "game/特殊牌(1).png");

    render_player_init_loader(loader);
    PIXI.CardSpirte.init_loader(loader);

    loader.onError.add(err => console.error(err))
    this.draw_app = async () => {
      console.log("DRAW GAMING");
      const loader = this.loader;
      if (!loader) {// maybe run on after destroyed
        return
      }
      this.clearWatch();
      const resources = loader.resources;
      app.stage.destroy();
      const stage = app.stage = new PIXI.Container();
      const {
        width,
        height
      } = app.renderer;
      const bg = new PIXI.Sprite(resources.bg.texture);
      bg.width = width;
      bg.height = height;
      stage.addChild(bg);

      const {
        avatar_box_bounds
      } = await render_player.call(this, {
          app,
          stage,
          resources,
          width,
          height,
          unwatchers,
        });

      // 摆牌面板
      const $gaming_panel = new PIXI.Container();
      stage.addChild($gaming_panel);
      const $gaming_bg = new PIXI.Sprite(resources.gaming_bg.texture);
      $gaming_bg.maxWidthHeight(width * .7, height * .5);
      $gaming_bg.x = width / 2 - $gaming_bg.width / 2;
      $gaming_bg.y = $gaming_bg.height * .15;
      $gaming_panel.addChild($gaming_bg);
      // 提交按钮
      const $done_btn = new PIXI.Sprite(resources.done_btn.texture);
      $done_btn.hoverSprite(resources.done_hover_btn.texture);
      $done_btn.bindTap(this.submitRes.bind(this));
      $done_btn.maxWidth(avatar_box_bounds.width * 1.5);
      let _is_done_btn_to_right;
      if (width - $gaming_bg.width > avatar_box_bounds.width * 4) {
        // 把按钮放置倒右边
        _is_done_btn_to_right = true
      } else if (width - $gaming_bg.width > avatar_box_bounds.width * 2) {
        // 把按钮放置倒右边并且改变背景面板的坐标
        _is_done_btn_to_right = true
        $gaming_bg.x = width - $gaming_bg.width - avatar_box_bounds.width * 2;
      } else {
        _is_done_btn_to_right = false
      }
      const gaming_bg_bounds = $gaming_bg.getBounds();
      if (_is_done_btn_to_right) {
        $done_btn.x = gaming_bg_bounds.right + avatar_box_bounds.width * .2;
        $done_btn.y = gaming_bg_bounds.bottom - $done_btn.height;
      } else {
        $done_btn.x = width / 2 - $done_btn.width / 2
        $done_btn.y = gaming_bg_bounds.bottom + $done_btn.height * 0.2;
      }
      $gaming_panel.addChild($done_btn);
      /* 重置按钮，与遮罩面板 */
      // 头，中，尾
      ["top", "mid", "btm"].forEach((key, i) => {
        const $clear_card_list = new PIXI.Sprite(resources.clear_btn.texture);
        $clear_card_list.hoverSprite(resources.clear_hover_btn.texture);
        $clear_card_list.maxWidth(gaming_bg_bounds.width * 0.06);
        $clear_card_list.x = gaming_bg_bounds.right - gaming_bg_bounds.width * 0.12;
        if (i === 0) {
          // $clear_card_list.x = gaming_bg_bounds.right-gaming_bg_bounds.width*0.25;
          $clear_card_list.y = gaming_bg_bounds.top + gaming_bg_bounds.height * .1;
        } else if (i === 1) {
          // $clear_card_list.x = gaming_bg_bounds.right-gaming_bg_bounds.width*0.15;
          $clear_card_list.y = gaming_bg_bounds.top + gaming_bg_bounds.height * .31;
        } else {
          $clear_card_list.y = gaming_bg_bounds.top + gaming_bg_bounds.height * .6;
        }
        $clear_card_list.bindTap(() => {
          this.removeFromResCards(key + '_card_list');
        })
        $gaming_panel.addChild($clear_card_list);
        unwatchers[unwatchers.length] = this.$watch(key + "_card_list.length", has_len => {
          $clear_card_list.visible = !!has_len
        }, {
            immediate: true
          });

        const $cards_mask = new PIXI.Sprite(resources["cards_mask_" + key].texture);
        if (i === 0) {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.376);
          $cards_mask.x = gaming_bg_bounds.left + gaming_bg_bounds.width * 0.325;
          $cards_mask.y = gaming_bg_bounds.top + gaming_bg_bounds.height * 0.06;
        } else if (i === 1) {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.578);
          $cards_mask.x = gaming_bg_bounds.left + gaming_bg_bounds.width * 0.224;
          $cards_mask.y = gaming_bg_bounds.top + gaming_bg_bounds.height * 0.29;
        } else {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.64);
          $cards_mask.x = gaming_bg_bounds.left + gaming_bg_bounds.width * 0.192;
          $cards_mask.y = gaming_bg_bounds.top + gaming_bg_bounds.height * 0.505;
        }
        $gaming_panel.addChild($cards_mask);
        $cards_mask.bindTap(() => {
          this.addSelectedCardsToRes(key + '_card_list', key === 'top' ? 3 : 5);
        });
        unwatchers[unwatchers.length] = this.$watch(key + "_card_list", card_list => {
          $cards_mask.children.slice().forEach(child => child.destroy());
          card_list.forEach((card, i) => {
            const $card = new PIXI.CardSpirte(card, resources);
            if (key === "top") {
              $card.x = $card.width * (i * .58 - 0.02);
            } else if (key === "mid") {
              $card.x = $card.width * (i * .577 - 0.03);
            } else {
              $card.x = $card.width * (i * .68 - 0.03);
            }
            $cards_mask.addChild($card);
          });
          // cards.
        }, {
            immediate: true
          });
      });

      unwatchers[unwatchers.length] = this.$watch("player.status", (status) => {
        $gaming_panel.visible = true;
        if (status === PLAYER_STATUS.BEFORE_SUBMIT) {
          $gaming_panel
        } else {
          $ready_button.visible = false
        }
      }, { immediate: true });

      // 底部智能选牌部分
      const $auto_btm_list = new PIXI.Container();
      stage.addChild($auto_btm_list);
      const auto_btm_list = [
        "two",
        "two_pair",
        "three",
        "straight",
        "flush",
        "full_house",
        "four",
        "straight_flush",
        "special"
      ];
      let acc_width = 0;
      const btm_height = width * 0.0562;
      auto_btm_list.forEach((type, i) => {
        const $btm = new PIXI.Sprite(resources["auto_" + type].texture);
        $btm.maxHeight(btm_height);
        $btm.x = acc_width - btm_height / 2 * i;
        acc_width += $btm.width;
        $auto_btm_list.addChild($btm);

        if (type === "special") {
          unwatchers[unwatchers.length] = this.$watch("is_special", is_special => {
            $btm.tint = is_special ? 0xFFFFFF : 0x999999;
          }, {
              immediate: true
            });
          $btm.bindTap(() => {
            this.submitResWithSpecial();
          });
        } else {
          let cards_list;
          let _p = 0;
          unwatchers[unwatchers.length] = this.$watch("com_" + type + "_list", res_list => {
            cards_list = res_list;
            _p = 0;
            if (res_list.length) {
              $btm.tint = 0xFFFFFF;
            } else {
              $btm.tint = 0x999999;
            }
          }, {
              immediate: true
            });
          $btm.bindTap(() => {
            _p = _p % cards_list.length;
            const cards = cards_list[_p];
            if (cards) {
              this.card_list.forEach(card => this.selectCard(card, false));
              cards.forEach(card => this.selectCard(card, true))
              _p += 1;
            }
          });
        }

      });
      $auto_btm_list.y = height - $auto_btm_list.height;

      // 渲染手牌
      const $hand_card_list = new PIXI.Container();
      $hand_card_list.interactive = true;
      $hand_card_list.on("pointerupoutside", () => {
        this.endSelectCard();
      });
      let hand_card_list_bounds
      $hand_card_list.on("pointermove", (e) => {
        const touch_point = e.data.global;
        if (!hand_card_list_bounds || !hand_card_list_bounds.contains(touch_point.x, touch_point.y)) {
          return
        }
        // 倒序，牌的坐标是覆盖的
        for (let i = card_list_bounds.length - 1; i >= 0; i -= 1) {
          const { card_index, bounds } = card_list_bounds[i];
          if (bounds.contains(touch_point.x, touch_point.y)) {
            this.trySelectCard(card_index)
            break;
          }
        }
      });
      const card_list_bounds = [];
      stage.addChildBefore($hand_card_list, $auto_btm_list);
      //card_list是deep监测来进行渲染，所以任意的操作都会造成手牌重绘，所以必须使用WeakMap对象来避免创建与销毁的开销。
      const hand_card_list_cache = new PIXI.CardListCache();
      unwatchers[unwatchers.length] = this.$watch("card_list", card_list => {
        while ($hand_card_list.children.length) {
          $hand_card_list.removeChildAt(0)
        }
        card_list_bounds.length = 0;
        card_list.forEach((card, card_index) => {
          const $card = hand_card_list_cache.get(card, resources);
          $card.maxWidthHeight(width * 0.15, height * 0.2, () => {
            // use maxwidth
            $card.x = card_index * width * .07;
          }, () => {
            // use maxheight
            $card.x = card_index * width * .05;
          });
          $hand_card_list.addChild($card);
          $card.tint = card.is_used ? 0x999999 : 0xFFFFFF;
          $card.y = card.is_selected ? ($card.height * -0.2) : 0;
          if (!$card.__is_inited_bind_tap) {
            $card.__is_inited_bind_tap = true;
            $card.interactive = true;
            $card.buttonMode = true;
            $card.on("pointerdown", () => {
              this.startSelectCard(card, card_index)
            });
            // $card.on("pointermove", (e) => {
            //   if (e.target === e.currentTarget) {
            //     this.trySelectCard(card_index)
            //   }
            // });
            $card.on("pointerup", () => {
              this.endSelectCard()
            });
          }
        });
        if ($hand_card_list.children.length) {
          const card_height = $hand_card_list.children[0].height;
          $hand_card_list.y = height - card_height - $auto_btm_list.height * 0.9;
          $hand_card_list.x = width / 2 - $hand_card_list.width / 2;
        }
        // 获取所有牌的坐标
        $hand_card_list.children.forEach(($card, card_index) => {
          card_list_bounds.push({
            bounds: $card.getBounds(),
            card_index
          })
        });
        hand_card_list_bounds = $hand_card_list.getBounds();
      }, {
          immediate: true,
          deep: true
        });
    }
  },
  methods: {
    roomStatusToString,
    playerStatusToString,
    cartNameToHtml(card) {
      const card_info = card.split("_");
      const [type, num] = card_info;
      const symbol_map = {
        "黑桃": "♠",
        "方块": "♦",
        "红心": "♥",
        "梅花": "♣",
      };
      const color_map = {
        "黑桃": "#000",
        "方块": "#e30",
        "红心": "#F00",
        "梅花": "#333",
      };
      return `<div class='img' style="color:${color_map[type]};">
        <div class='symbol'>${symbol_map[type]}</div>
        <div class='number'>${num}</div>
      </div>`
    },
    addSelectedCardsToRes(res_type, limit_num = 5) {
      const selected_cards = this.card_list.filter(card => card.is_selected);
      if (selected_cards.length === limit_num) {
        if (this[res_type].length) {
          this[res_type].forEach(card => {
            card.is_selected = true;
            card.is_used = false;
          });
        }
        this[res_type] = selected_cards;
        selected_cards.forEach(card => {
          card.is_selected = false;
          card.is_used = true
        });
        // 自动填充最后的牌组
        const rest_card_list = this.card_list.filter(card => !card.is_used);
        if (rest_card_list.length === 5 || rest_card_list.length === 3) {
          const key = ["top", "mid", "btm"].find(key => this[key + "_card_list"].length === 0);
          if (!key) {
            return
          }
          rest_card_list.forEach(card => card.is_selected = true);
          this.addSelectedCardsToRes(key + "_card_list", rest_card_list.length);
        }
      }
    },
    removeFromResCards(res_type) {
      const res_cards = this[res_type];
      res_cards.forEach(card => {
        card.is_used = false
        card.is_selected = true
      });
      this[res_type] = [];
    },
    selectCard(card_item, v = !card_item.is_selected) {
      if (!card_item.is_used) {
        card_item.is_selected = v;
      }
    },
    startSelectCard(card_item, card_index) {
      this.mul_select_from = card_index;
      this.selectCard(card_item);
      this.mul_select_val = card_item.is_used ? null : card_item.is_selected;
      this.mul_select_old_vals = this.card_list.map(card => card.is_selected);
    },
    trySelectCard(card_index) {
      if (this.mul_select_from !== null) {
        this.mul_select_to = card_index;
        const slice_from = Math.min(this.mul_select_from, this.mul_select_to);
        const slice_to = Math.max(this.mul_select_from, this.mul_select_to);
        this.card_list.forEach((card, i) => {
          if (i >= slice_from && i <= slice_to) {
            if (this.mul_select_val === null && !card.is_used) {
              this.mul_select_val = !card.is_selected;
            }
            this.selectCard(card, this.mul_select_val)
          } else {
            this.selectCard(card, this.mul_select_old_vals[i])
          }
        });
      }
    },
    endSelectCard() {
      this.mul_select_from = null;
      this.mul_select_to = null;
      this.mul_select_val = null;
      this.mul_select_old_vals = null;
    },

    submitResWithSpecial() {
      const special_info = this.special_info;
      if (special_info && special_info.type) {
        if (special_info.combination && special_info.combination.length) {
          const combination = special_info.combination[0];
          ["top",
            "mid",
            "btm",
          ].forEach(type => {
            this[`${type}_card_list`] = combination[type].map(card_txt => {
              const card = Card.getIns(card_txt);
              card.is_used = true;
              return card;
            });
          });
          const top_card_list = this.top_card_list;
          const mid_card_list = this.mid_card_list;
          const btm_card_list = this.btm_card_list;
          socket.emit("submit-res", {
            type: special_info.type,
            top: top_card_list,
            mid: mid_card_list,
            btm: btm_card_list,
          });
        } else {
          socket.emit("submit-res", {
            type: special_info.type,
            all: this.card_list,
          });
        }
      }
    },
    submitRes() {
      const top_card_list = this.top_card_list;
      const mid_card_list = this.mid_card_list;
      const btm_card_list = this.btm_card_list;
      socket.emit("submit-res", {
        top: top_card_list,
        mid: mid_card_list,
        btm: btm_card_list,
      });
    },
    submitChangedCardList() {
      const selected_card_list = CARD_LIST.filter(card => card.is_selected);
      if (selected_card_list.length !== 13) {
        alert(`选中了${selected_card_list.length}张，必须选13张`)
        return;
      }
      CARD_LIST.forEach(card => {
        card.reset();
      });
      socket.emit("--changed-card-list--", selected_card_list)
    }
  }
})
</script>
<style>
@import url('./Gaming.css');
.gaming {
  height: 100%;
  width: 100%;
}
</style>